<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
    body {
        margin: 0;
    }

    #box {
        width: 600px;
        margin: 50px auto;

    }

    #map {
        width: 600px;
        height: 400px;
        background-color: darkgray;
        position: relative;
    }
</style>

<body>
    <div id="box">
        <button id="start">开始游戏</button>
        <button id="end">结束游戏</button>
        <button id="stop">暂停游戏</button>
        <div id="map"></div>
    </div>
</body>

</html>
<script>
    // 贪吃蛇 实现思路 先分为两大类 蛇 和 食物
    //  创建一个公共类，用来保存工具函数
    class Tool {
        // 获取元素
        $ = id => document.getElementById(id)
        // 创建元素
        _c = tagName => document.createElement(tagName)
    }

    //1      有个类来控制蛇
    class Sneak extends Tool {
        constructor(food) {
            // 获取map 
            super()
            this.map = this.$('map')
            // 定义蛇的每一节 width,height
            this.width = 20
            this.height = 20
            // 定义蛇的身子，他们的初始X轴 Y轴坐标
            this.body = [
                { x: 2, y: 0 },     //蛇头坐标
                { x: 1, y: 0 },
                { x: 0, y: 0 }      //蛇尾坐标
            ]
            // 定义蛇的初始运动方向为右
            this.direction = 'right'
            this.display()
        }
        // // 获取元素
        //  $ = id =>document.getElementById(id)
        // // 创建元素
        // _c = tagName => document.createElement(tagName)
        //2      先根据this.body里面的数据，创建蛇身
        display() {
            this.body.forEach(item => {
                if (item.olddiv) {
                    this.map.removeChild(item.olddiv)
                }
                let div = this._c('div')
                this.div = div
                //  蛇身添加属性
                div.style.width = this.width + 'px'
                div.style.height = this.height + 'px'
                div.style.backgroundColor = 'hotpink' //'rgb(' + parseInt(Math.random() * 256) + ',' + parseInt(Math.random() * 256) + ',' + parseInt(Math.random() * 256) + ')'
                // div.style.border = 'solid 1px black'
                div.style.borderRadius = '8px'
                //  div 排列是垂直排放的，需要定位将他们水平排列。
                div.style.position = 'absolute'
                // 控制每个 div 定位的位置 每个 div 的位置。应该是 div的宽度乘以它的 X 值 ， 
                // 这里是遍历了数组中的每一个 item ，因为 item 是一个对象，要获取它的 X 属性值，应该用 item.x  console.log(item.x);
                div.style.left = item.x * this.width + 'px'
                // div 的 top 值 也是他的 y 的值
                div.style.top = item.y * this.width + 'px'
                item.olddiv = div
                //  将蛇身添加到 map 
                this.map.appendChild(div)
                // console.log(item);
            })
        }
        //3       定义蛇动起来的方法 
        run() {
            // this.body.olddiv
            // 要根据用户按下的方向键，让蛇动起来。首先在构造器里先定义蛇的默认运动方向为右， 根据用户按下的方向键来控制蛇的方向。 
            // 获取头部
            let tail = this.body.pop()
            this.keyBoardEvent()
            // let head = this.body[0]
            let head = this.body[0]
            // let {x} = head
            // let {y} = head
            let x = head.x
            let y = head.y

            switch (this.direction) {
                case 'left':
                    x -= 1
                    break;
                case 'right':
                    x += 1
                    break;
                case 'up':
                    y -= 1
                    break;
                case 'down':
                    y += 1
                    break;
            }
            // console.log(x, y);
            // console.log(this.direction);
            // 如何让蛇动起来？ 在 X 轴上 将蛇的尾部切掉，让蛇的尾部 X 值 等于 蛇头 X 值 +1 ，再将尾部重新插入蛇头前面当作新的蛇头
            // 获取尾部

            tail.x = x
            tail.y = y
//  6 边界判断 
        // X轴最小为 0  最大为 map 的宽度 减去 一截身体的宽度
        // Y轴最小为 0  最大为 map 的高度 减去 一截身体的高度
                  

        //    console.log(tail.x,tail.y);
        let tailleft = tail.x * this.width
        let tailtop = tail.y * this.height
        if (tailleft < 0 || tailleft >this.map.offsetWidth -this.div.offsetWidth){
                // btnEvent.stop()
             } 
        if(tailtop < 0 || tailtop > this.map.offsetHeight -this.div.offsetHeight){
            // btnEvent.stop()
        }
        // console.log(food.fooddivX)
        // console.log(food.fooddivY)
        // 蛇头位置 和 食物位置重合时，判定吃到食物，往body里推进一个对象。增加一节身体，
        if (tailleft === food.fooddivX && tailtop === food.fooddivY){
            this.body.push({x,y})
            food.removefood()
            food.createfood()
        }
        // console.log(tailtop);
        // console.log(tailleft);
            // console.log(tail);
            // 将重新赋值后的尾部，添加到头部
            this.body.unshift(tail)
            this.display()
        }
        //4      按钮的功能实现
        btnEvent() {
            // 获取 start stop end 这三个btn
            let start = this.$('start')
            let end = this.$('end')
            let stop = this.$('stop')
            let timer = null
            // 注册点击事件
            start.onclick = () => {
                if(food.fooddiv){
                    return
                }else{
                    food.createfood()
                }
                // food.createfood()
                timer = setInterval(() => {
                    sneak.run()
                }, 200);
                console.log(123);
            }
            stop.onclick = () => {
                clearInterval(timer)
            }
            end.onclick = ()=>{
                clearInterval(timer)
                // food.removefood()
                this.map.innerHTML = ''

                this.body = [
                { x: 2, y: 0 },     //蛇头坐标
                { x: 1, y: 0 },
                { x: 0, y: 0 }      //蛇尾坐标
            ]
            this.display()
            }
        }
        // 5    键盘事件，确认用户按下的是哪个方向键
        keyBoardEvent() {
            document.onkeydown = (e) => {
                // console.log(e);
                switch (e.keyCode) {
                    case 37:
                        if(this.direction != 'right'){
                            this.direction = 'left'
                        }
                        break;
                    case 38:
                        if(this.direction != 'down'){
                            this.direction = 'up'
                        }
                        break;
                    case 39:
                        if(this.direction != 'left'){
                            this.direction = 'right'
                        }
                        break;
                    case 40:
                        if(this.direction != 'up'){
                            this.direction = 'down'
                        }
                }
            }
        }

    }

    // 2.有个类来控制食物
    class Food extends Tool{
        constructor() {
            super()
            this.width = '20'
            this.height = '20'
        }
        // 创建food
        createfood(){
            this.fooddiv = this._c('div')
            this.fooddiv.style.backgroundColor = 'rgb('+parseInt(Math.random() * 256)+','+parseInt(Math.random() * 256)+','+parseInt(Math.random() * 256)+')'
            this.fooddiv.style.width = this.width +'px'
            this.fooddiv.style.height = this.height +'px'
            // div 出现的位置，x轴 最小为 0 ，最大 为 map 的宽度 
            // div 出现的位置，y轴 最小为 0 ，最大 为 map 的高度
            this.fooddiv.style.position = 'absolute'
            this.fooddiv.style.borderRadius = '8px'
            // console.log(sneak.map.offsetWidth);
            this.fooddivX = parseInt(Math.random() * 30) *20
            this.fooddivY = parseInt(Math.random() * 20) *20
            this.fooddiv.style.left = this.fooddivX + 'px' 
            this.fooddiv.style.top = this.fooddivY + 'px' 
            sneak.map.appendChild(this.fooddiv)
        }
        removefood(){
            sneak.map.removeChild(this.fooddiv)
        }
        // eat (){
        //     console.log(sneak.body[0].x,sneak.body[0].y);
        //     let sneakdivleft = (sneak.body[0].x +1) * sneak.width
        //     let sneakdivtop = (sneak.body[0].y +1) * sneak.width
        //     console.log(sneakdivleft);
        //     console.log(sneakdivtop);
        //     if(sneakdivleft === this.fooddiv.style.top && sneakdivtop === this.fooddiv.style.left ){
        //         sneak.body.appendChild(this.fooddiv)
        //     console.log(this.fooddiv.style.left);
        //     }
        // }

    }
    let food = new Food()
    let sneak = new Sneak(food)
    sneak.btnEvent()
  

</script>